from django.shortcuts import render, HttpResponse, redirect
import hashlib
from django.conf import settings
from manager.models import *
import datetime
from django.http import JsonResponse
"""
加载极验模块
"""
from geetest import GeetestLib

# 自定义功能模块
from utils import verify, common


# Create your views here.
# 登录接口，验证登录信息
def login(request):
    # 声明一个空的变量，用来存放错误信息，向页面响应
    if request.method == 'POST':
        """
        如果是post请求，直接调用_checkLogin函数，来检查输入的用户名和密码是否正确
        然后将函数的返回值获取到
        返回值要么是一个错误信息（字符串）要么是一个queryset集合
        """
        managerInfo = _checkLogin(request)
        # 通过类型来判断返回的值是否是一个错误信息
        if isinstance(managerInfo, str):
            # 如果是一个错误信息，直接将错误信息渲染到html中
            return render(request, 'backstage/login.html', {'error': managerInfo})
        # adminInfo[0] = {'id':1,'account':'admin',"pwd":''} 字典（用户信息）
        # 获取客户端ip
        client_ip = request.META['REMOTE_ADDR']
        # 获取当前时间
        dt = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')

        # 记录本次管理员登录日志
        admin_log = {
            "type": '登录',
            "title": managerInfo[0]['account'] + '登录',
            "user_agent": request.META['HTTP_USER_AGENT'],
            'referer': request.META['HTTP_REFERER'],
            'add_time': dt,
            'ip': client_ip,
            'admin_id': managerInfo[0]['id']
        }
        # 更新当前用户的信息
        manager = Manager.objects.get(id=managerInfo[0]['id'])
        manager.login_ip = client_ip
        manager.login_time = dt
        manager.login_num += 1
        manager.save()

        # 向日志表添加数据，使用双**方法，会自动将数据拆分并逐条遍历写入数据库中
        Manager_log.objects.create(**admin_log)

        request.session['user'] = managerInfo[0]

        return redirect('/manager/index/')
    return render(request, 'backstage/login.html')
# 极验后端验证端口（连接向极验服务器）
def pcgetcaptcha(request):
    user_id = 'test'
    gt = GeetestLib('4726b9849ea9f2493787a3fa247a9973', 'c264c310dbae53a1383770771408b473')
    status = gt.pre_process(user_id)
    request.session[gt.GT_STATUS_SESSION_KEY] = status
    request.session["user_id"] = user_id
    response_str = gt.get_response_str()
    return HttpResponse(response_str)

# 退出登录接口，删除cookie及session
def logout(request):
    request.session.delete()
    return redirect('/manager/login/')


# 验证码验证接口，展示验证码
def get_verify(request):
    """
    通过调用模块中的生成验证码图片函数，生成一个验证码
    这个验证码返回的是一个元组，元组内的第一个元素是图片的内容，第二个元素是验证码的详情
    :param request:
    :return:
    """
    verifys = verify.get_verify()
    # 将验证码放入到session中，等待登录验证
    request.session['verifys'] = verifys[1]
    """
    向浏览器响应一个png格式的验证码图片
    由前端的js代码接收，然后放入到指定标签中
    """
    return HttpResponse(verifys[0], content_type='image/png')


# 后台首页，用来展示后台功能
def index(request):
    """
    后台首页，返回的值是用来区分用户的身份的
    :param request:
    :return:
    """
    admin = request.session.get('user')['id']
    log1 = Manager_log.objects.filter(admin=admin).values().order_by('-id')
    last_addtime = log1[1]['add_time']
    last_logip = log1[1]['ip']
    menu = settings.MENU
    data = {
        'user': request.session.get('user'),
        'menu': menu,
        'last_logip':last_logip,
        'last_addtime':last_addtime
    }
    return render(request, 'backstage/index.html', data)


"""
验证登录方法，此方法是在视图内做登录的验证
将登录接口中对于用户名及密码等信息的判断逻辑剔除出来，单独封装成一个函数
在登录的接口内被调用，让代码看起来更简洁，使登录的接口不臃肿,增加代码可读性
"""


def _checkLogin(request):
    # 获取用户名
    account = request.POST.get('account', None).strip()
    # 获取密码
    pwd = request.POST.get('pwd', None).strip()

    if request.method == "POST":
        gt = GeetestLib('4726b9849ea9f2493787a3fa247a9973', 'c264c310dbae53a1383770771408b473')
        challenge = request.POST.get(gt.FN_CHALLENGE, '')
        validate = request.POST.get(gt.FN_VALIDATE, '')
        seccode = request.POST.get(gt.FN_SECCODE, '')
        status = request.session[gt.GT_STATUS_SESSION_KEY]
        user_id = request.session["user_id"]
        if status:
            result = gt.success_validate(challenge, validate, seccode, user_id)
        else:
            result = gt.failback_validate(challenge, validate, seccode)
        # result = {"status":"success"} if result else {"status":"fail"}
        # return HttpResponse(json.dumps(result))
        if not result: return '验证失败！'
    # 获取验证码
    # code = request.POST.get("code", None).strip()

    # if not code:
    #     return '验证码不能为空'
    # if code.lower() != request.session.get('verifys').lower():
    #     return '验证码不正确，请重新输入验证码！'
    if not account or not pwd:
        return '用户名或密码不能为空！'
    # 根据前端传来的用户名来过滤数据库内的管理员数据
    managerInfo = Manager.objects.filter(account=account).values('id', 'account', 'pwd', 'login_ip', 'login_num',
                                                                 'state')
    if len(managerInfo) <= 0:
        return '用户名或密码错误，请重新输入!'
    if not managerInfo[0]['state']:
        return '您的账户已被禁用，请联系管理员'
    # 将客户端输入的密码加盐
    pwd = settings.SALT + pwd + settings.SALT
    # 实例化哈希对象
    md5 = hashlib.md5()
    # 将客户端传入的密码进行哈希
    md5.update(pwd.encode('utf-8'))
    # 获取哈希后的密文
    pwd = md5.hexdigest()
    # 将客户端传入的密码哈希值与服务器中的密码哈希值进行对比判断
    if managerInfo[0]['pwd'] != pwd:
        return '用户名或密码错误，请重新输入！'
    return managerInfo


# 管理员管理页面
def member(request):
    # 获取到数据库中所有的管理员数据
    manager = Manager.objects.filter(id__gt=1).values('id', 'account', 'mobile', 'email', 'state', 'login_time')
    # 获取功能菜单
    menu = settings.MENU
    # 把将要传到页面的数据组织好数据
    data = {
        # 这里使用的是get请求，得到页面使用ajax使用get的方式传来的用户名
        "user": request.session.get('user'),
        # 功能列表数据
        "menu": menu,
        # 管理员数据
        'manager': manager,
        # 管理员的数量
        'count': manager.count()
    }
    return render(request, 'backstage/member/member.html', data)


# 添加管理员
def member_add(request):
    if request.is_ajax():
        # 使用dict方法直接将前端传来的数据转换成一个字典
        data = dict(request.POST)
        # 判断两次输入的密码是否相同
        if data['pwd'] != data['pwd2']:
            return JsonResponse({
                'msg': '两次输入的密码不一致！',
                'code': 1,
                'data': []
            })
        # TODO 待优化
        # 对前台传递过来的密码进行hash
        print(data['pwd'][0])
        pwd = settings.SALT + str(data['pwd'][0]) + settings.SALT
        # 实例化哈希中的md5方法
        md5 = hashlib.md5()
        # 将密码转码后转为哈希值
        md5.update(pwd.encode('utf-8'))
        # 获取到哈希后的密码
        pwd = md5.hexdigest()
        try:
            Manager.objects.create(account=data['account'][0], pwd=pwd, mobile=data['mobile'][0],
                                   email=data['email'][0])
        except Exception as e:
            print(e)
            msg = '网络异常，请联系开发人员'
            return JsonResponse({'msg': msg, 'code': 2, 'data': []})
        return JsonResponse({'msg': '添加成功！', 'code': 0, 'data': []})
    return render(request, 'backstage/member/member_add.html')


# 改变管理员状态
def member_change_state(request):
    # 获取到页面发送的id值
    id = request.GET.get("id")
    # 判断是否获取到了id值
    if not id:
        return JsonResponse({'msg': '请选择要修改的管理员数据', 'code': 1, 'data': []})
    # 从数据库获取到指定id的数据
    member = Manager.objects.get(id=id)
    """
    对指定id的指定状态的数据进行修改
    语法糖，我们在数据库中对状态的数据设置的是布尔值
    当点击切换状态的时候，我们对现在的状态进行判断
    也就是说，只要点击了，必定会改变成与其之前状态值相反的状态值
    """
    member.state = False if member.state else True
    # 保存修改
    member.save()

    return JsonResponse({'msg': '修改成功！', 'code': 0, 'data': [member.state]})


# 删除管理员
def member_del(request):
    id = request.GET.get('id')
    if not id:
        return JsonResponse({'msg': '请选择要删除的管理员数据', 'code': 1, 'data': []})
    # 如果获取到了指定的id值,找到该id值并删除其数据
    Manager.objects.get(id=id).delete()
    return JsonResponse({'msg': '删除成功！', 'code': 0, 'data': []})


# 修改管理员信息
def member_edit(request):
    # ajax请求  返回的都是json

    if request.is_ajax():
        id = request.POST.get('id', 0)
        pwd = request.POST.get('pwd', '')
        pwd2 = request.POST.get('pwd2', '')
        email = request.POST.get('email', '')
        mobile = request.POST.get('mobile', '')
        if not id:
            return JsonResponse({'msg': '要修改的管理员id不能为空！', 'code': 2, 'data': []})

        data = Manager.objects.get(id=id)
        # 只修改管理员信息，不修改密码
        if pwd and pwd2:
            if pwd != pwd2:
                return JsonResponse({'msg': '输入的两次密码不一致！', 'code': 1, 'data': []})
            # TODO 待优化
            # 对前台传递过来的密码进行hash
            pwd = settings.SALT + pwd + settings.SALT
            # 参与哈希运算
            md5 = hashlib.md5()
            md5.update(pwd.encode('utf-8'))
            # 获取哈希后的密文
            pwd = md5.hexdigest()
            # 更新密码
            data.pwd = pwd

        # 修改邮箱
        if data.email != email: data.email = email
        # 修改手机
        if data.mobile != mobile: data.mobile = mobile
        # 更新当前管理员信息
        data.save()
        return JsonResponse({'msg': '操作成功！', 'code': 0, 'data': []})
    id = request.GET.get('id')
    if not id:
        """
        使用自定义功能模块直接将错误的弹出框以html标签的格式响应到页面中
        """
        html = common.msg('请选择要修改的管理员！')
        return HttpResponse(html)
    try:
        # 获取到指定id的管理员信息
        data = Manager.objects.get(id=id)
    except Exception as e:
        html = common.msg('修改异常，请联系管理员')
        return HttpResponse(html)
    return render(request, 'backstage/member/member_edit.html', {'data': data})
